package com.tianma315.admin.stock.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.tianma315.admin.check.domain.CheckArrtDO;
import com.tianma315.admin.check.domain.RecordArrtDO;
import com.tianma315.admin.check.service.CheckArrtService;
import com.tianma315.admin.common.base.CoreServiceImpl;
import com.tianma315.admin.common.exception.HtmlCodeException;
import com.tianma315.admin.common.exception.MessageException;
import com.tianma315.admin.common.utils.Result;
import com.tianma315.admin.material.VO.PurchaseAndArrtVO;
import com.tianma315.admin.oss.service.FileService;
import com.tianma315.admin.product.domain.Product;
import com.tianma315.admin.product.service.ProductService;
import com.tianma315.admin.stock.dao.StockDao;
import com.tianma315.admin.stock.dao.WarehousingRecordDao;
import com.tianma315.admin.stock.domain.Stock;
import com.tianma315.admin.stock.domain.WarehousingRecord;
import com.tianma315.admin.stock.domain.vo.WarehousingRecordAndArrtVO;
import com.tianma315.admin.stock.domain.vo.WarehousingRecordVo;
import com.tianma315.admin.stock.service.StockService;
import com.tianma315.admin.util.CellUtil;
import com.tianma315.admin.util.HiddenSheetUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

//                   _ooOoo_
//                  o8888888o
//                  88" . "88
//                  (| -_- |)
//                  O\  =  /O
//               ____/`---'\____
//             .'  \\|     |//  `.
//            /  \\|||  :  |||//  \
//           /  _||||| -:- |||||-  \
//           |   | \\\  -  /// |   |
//           | \_|  ''\---/''  |   |
//           \  .-\__  `-`  ___/-. /
//         ___`. .'  /--.--\  `. . __
//      ."" '<  `.___\_<|>_/___.'  >'"".
//     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//     \  \ `-.   \_ __\ /__ _/   .-` /  /
//======`-.____`-.___\_____/___.-`____.-'======
//                   `=---='
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//         佛祖保佑       永无BUG

/**
 * Description
 * <p>
 * Created by zcm on 2019/5/28.
 */
@Service
@Transactional
public class StockServiceImpl extends CoreServiceImpl<WarehousingRecordDao, WarehousingRecord> implements StockService {
    @Autowired
    private StockDao stockDao;
    @Autowired
    private WarehousingRecordDao warehousingRecordDao;

    @Autowired
    private ProductService productService;

    @Autowired
    private CheckArrtService checkArrtService;
    @Autowired
    private FileService sysFileService;

    @Override
    public Page<WarehousingRecordVo> getPage(int pageNumber, int pageSize, String searchKey) {
        Page page = new Page(pageNumber, pageSize);
        page.setRecords(warehousingRecordDao.selectRecordPage(page, searchKey));
        return page;
    }

    @Override
    public boolean save(WarehousingRecord record) {
        record.setStatus(WarehousingRecord.STATUS_ENABLE);
        if (warehousingRecordDao.insert(record) != 1)
            throw new MessageException("入库失败");


        Stock stock;
        List<Stock> stocks = stockDao.selectList(new EntityWrapper<Stock>() {{
            eq("product_id", record.getProductId());
        }});

        if (stocks == null || stocks.isEmpty()) {
            stock = new Stock();
            stock.setProductId(record.getProductId());
            stock.setNumber(record.getNumber());
            if (stockDao.insert(stock) != 1)
                throw new MessageException("库存添加失败");
        } else {
            stock = stocks.get(0);
            stock.setProductId(record.getProductId());
            stock.setNumber(stock.getNumber() + record.getNumber());
            if (stockDao.updateById(stock) != 1)
                throw new MessageException("库存修改失败");
        }


        return true;
    }

    @Override
    public boolean revert(long record_id) {
        //删除记录
        WarehousingRecord warehousingRecord = warehousingRecordDao.selectById(record_id);
        warehousingRecord.setStatus(WarehousingRecord.STATUS_DELETE);
        if (warehousingRecordDao.updateById(warehousingRecord) != 1) {
            throw new MessageException("记录删除失败");
        }
        //修改库存
        List<Stock> stocks = stockDao.selectList(new EntityWrapper<Stock>() {{
            eq("product_id", warehousingRecord.getProductId());
        }});
        if (stocks == null || stocks.isEmpty()) {
            throw new MessageException("没有库存");
        }

        Stock stock = stocks.get(0);

        if (stock.getNumber() < warehousingRecord.getNumber()){
            throw new MessageException("库存不足，撤销失败");
        }

        stock.setNumber(stock.getNumber() - warehousingRecord.getNumber());
        if (stock.getNumber() < 0) {
            stock.setNumber(0);
        }
        if (stockDao.updateById(stock) != 1)
            throw new MessageException("库存更新失败");


        return true;
    }

    @Override
    @Transactional
    public boolean batchRevert(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            revert(ids[i]);
        }
        return true;
    }

    @Override
    public List<WarehousingRecordAndArrtVO> statisticsTable(Page page,List<Integer> productIds, Date beginDate, Date endDate) {
        return warehousingRecordDao.statisticsProductTable(page, productIds,beginDate,endDate);
    }

    @Override
    public List<WarehousingRecordAndArrtVO> statisticsAllTable(Date beginDate, Date endDate) {
        List<WarehousingRecordAndArrtVO> list =  warehousingRecordDao.statisticsProductAllTable(null,beginDate,endDate);
        List<WarehousingRecordAndArrtVO> resultList = new ArrayList<>();
        Map<Integer,WarehousingRecordAndArrtVO> map  =new HashMap<>();
        //进行统计检测的次数，及合并同一种原材料的检测记录
        Integer count = 1;//次数
        for (WarehousingRecordAndArrtVO p:list) {
            WarehousingRecordAndArrtVO po = map.get(p.getProductId());
            if (po == null){
                p.setCountNum(count);
                po = p;
            }else{
                po.setCountNum(po.getCountNum()+1);
                po.getRecordArrtVOS().addAll(p.getRecordArrtVOS());
            }
            map.put(p.getProductId(),po);
        }

        List<WarehousingRecordAndArrtVO> warehousingRecordAndArrtVOList = new ArrayList<>();
        for(WarehousingRecordAndArrtVO p :map.values()){
            warehousingRecordAndArrtVOList.add(p);
        }
        return warehousingRecordAndArrtVOList;
    }

    @Override
    public Page<WarehousingRecordAndArrtVO> warehousingRecordAndArrtInfo(
            Integer pageNumber,Integer pageSize, String productName, Date beginDate, Date endDate){
        Page<WarehousingRecordAndArrtVO> page = new Page(pageNumber, pageSize);
        List<WarehousingRecordAndArrtVO> warehousingRecordAndArrtVOs = warehousingRecordDao.statisticsProductPage(page, productName,beginDate,endDate);
        page.setRecords(warehousingRecordAndArrtVOs);
        return page;
    }

    @Override
    public Page<JSONObject> getDataJson(
            Integer pageNumber,Integer pageSize, String productName,
            Date beginDate, Date endDate) {
        Page<WarehousingRecordAndArrtVO> page = warehousingRecordAndArrtInfo(pageNumber,pageSize,productName,beginDate,endDate);
        List<WarehousingRecordAndArrtVO> wrList =  page.getRecords();
        Page<JSONObject> result = new Page<>(pageNumber,pageSize);
        result.setTotal(page.getTotal());
        result.setCurrent(page.getCurrent());

        JSONObject jsonObject = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        //表头
        List<String> boxHeadList = new ArrayList<>();
        List contentList = new ArrayList<>();

        if (wrList==null || wrList.isEmpty()){
            throw  new HtmlCodeException("未找到检测记录");
        }else {
            Set<String> set = new HashSet();
            List<CheckArrtDO> checkArrtDOList = checkArrtService.getCheckArrtList();
            for (CheckArrtDO checkArrtDO:checkArrtDOList) {
               set.add(checkArrtDO.getArrtName());
            }
            boxHeadList.addAll(set);

            for (int i = 0; i < wrList.size(); i++) {
                WarehousingRecordAndArrtVO wr = wrList.get(i);
                Integer orderNumber = i + 1;
                JSONObject obj = new JSONObject();
                obj.put("batch",wr.getBatch());
                obj.put("productName",wr.getProductName());
                obj.put("no",orderNumber);
                obj.put("checkBy",wr.getCheckBy());


                //遍历属性值
                List<RecordArrtDO> recordArrtDOS = wr.getRecordArrtDOList();
                List<CheckArrtDO> checkArrtDOS = wr.getCheckArrtDOList();
                Iterator<String> it = set.iterator();

                List<Map> dataList = new ArrayList<>();
                for (String str : set){
                    Map map = new HashMap();
                    map.put("attrValue",null);
                    for (int j = 0; j < recordArrtDOS.size(); j++) {
                        RecordArrtDO recordArrtDO = recordArrtDOS.get(j);
                        CheckArrtDO checkArrtDO = checkArrtDOS.get(j);
                        map.put("min",checkArrtDO.getMinimum());
                        map.put("max",checkArrtDO.getMaximum());

                        if(str.equals(checkArrtDO.getArrtName())){
                            map.put("attrValue",recordArrtDO.getArrtValues());
                            break;
                        }
                    }
                    dataList.add(map);
                }

                for (int j = 0; j < dataList.size(); j++) {
                    Map map = dataList.get(j);
                    String attrValue = (String) map.get("attrValue");
                    Double min = (Double) map.get("min");
                    Double max = (Double) map.get("max");
                    String data = "";
                    if (StringUtils.isNotEmpty(attrValue)){
                        double attr = Double.parseDouble(attrValue);
                        if (attr<min){
                            data = "<span style = color:blue;font-size:16px;font-weight:900 >"+attr+"</span>"+"("+min+"-"+max+")";
                        }else if(attr>max){
                            data = "<span style = color:red;font-size:16px> "+attr+"</span>"+"("+min+"-"+max+")";
                        }else{
                            data = "<span> "+attr+"</span>"+"("+min+"-"+max+")";
                        }
                    }else{
                        data = "("+min+"-"+max+")";
                    }
                    obj.put("checkArrt"+j,data);
                }


                contentList.add(obj);
            }
        }
        result.setRecords(contentList);
        return result;
    }


    @Override
    public List<JSONObject> getHead() {
        List<JSONObject> boxHeadList = new ArrayList<>();

        JSONObject batch = new JSONObject();
        batch.put("title","批次");
        batch.put("field","batch");
        boxHeadList.add(batch);
        JSONObject productName = new JSONObject();
        productName.put("title","产品名称");
        productName.put("field","productName");
        boxHeadList.add(productName);
        JSONObject no = new JSONObject();
        no.put("title","编号");
        no.put("field","no");
        boxHeadList.add(no);
        JSONObject checkBy = new JSONObject();
        checkBy.put("title","检测人");
        checkBy.put("field","checkBy");
        boxHeadList.add(checkBy);
        Set<String> set = new HashSet();
        List<CheckArrtDO> checkArrtDOList = checkArrtService.getCheckArrtList();
        for (CheckArrtDO checkArrtDO:checkArrtDOList) {
            set.add(checkArrtDO.getArrtName());
        }
        Integer i = 0;
        for(String str : set){
            JSONObject  obj = new JSONObject();
            obj.put("title",str);
            obj.put("field","checkArrt"+i);
            i++;
            boxHeadList.add(obj);
        }


        return boxHeadList;
    }

    @Override
    public HSSFWorkbook exportStock() {
        String[] title = {"入库日期","生产车间","产品名称","数量","仓库","批次","生产日期"};
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("原材料记录模板");

//        sheet.addMergedRegion(new CellRangeAddress(0,0,0,8));//第一行第一列开始，跨8列
        HSSFRow titleRow = sheet.createRow(0);//第0行

        //标题样式
        HSSFCellStyle titleStyle = wb.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short)18);
        titleStyle.setFont(font);

        //生成标题
        HSSFCell titleCell = titleRow.createCell(0);
        titleCell.setCellValue("产品记录模板（红色标识列为必填）");
        titleCell.setCellStyle(titleStyle);

        //红色字体
        HSSFCellStyle redStyle = wb.createCellStyle();
        redStyle.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont redFont = wb.createFont();
        redFont.setBold(true);
        redFont.setColor(Font.COLOR_RED);
        redStyle.setFont(redFont);

        //默认字体样式
        HSSFCellStyle defaultStyle = wb.createCellStyle();
        defaultStyle.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont defaultFont = wb.createFont();
        defaultFont.setBold(true);
        defaultStyle.setFont(defaultFont);

        //声明列对象
        HSSFCell cell = null;
        //创建表头
        HSSFRow headRow = sheet.createRow(1);
        for(int i=0; i<title.length; i++){
            //下标小于7是必填列
//            if (i < 7){
                cell = headRow.createCell(i);
                cell.setCellValue(title[i]);
                cell.setCellStyle(redStyle);
//            }else{
//                cell = headRow.createCell(i);
//                cell.setCellValue(title[i]);
//                cell.setCellStyle(defaultStyle);
//            }
        }

        List<Product> productS = productService.getAll();
        List<String> productList = productS.stream().map(item -> item.getProductName()).collect(Collectors.toList());
        String[] productNameArr = productList.toArray(new String[productList.size()]);


        String hiddenSheet = "hidden";
        Integer cellNum = 2;
        Integer startRow = 2; // 开始行
        Integer endRow = 10000; // 结束行

        HiddenSheetUtil.initHiddenSheet(hiddenSheet,wb,cellNum,startRow,endRow,productNameArr);
        //设置设备类型为下拉框选项
        DVConstraint constraint = DVConstraint.createFormulaListConstraint(hiddenSheet);
        // 设置数据有效性加载在哪个单元格上,四个参数分别是：起始行、终止行、起始列、终止列
        CellRangeAddressList regions = new CellRangeAddressList(startRow,
                endRow, cellNum, cellNum);
        HSSFDataValidation validation = new HSSFDataValidation(
                regions, constraint);
        wb.setSheetHidden(1, true);
        sheet.addValidationData(validation);

        return wb;
    }

    @Override
    @Transactional
    public void importStock(MultipartFile file, Long userId) {
        Boolean flag = CellUtil.isExcel(file.getOriginalFilename());
        if (!flag){
            throw new MessageException("只支持Excel文件");
        }

        List<Product> productList = productService.getAll();

        try {
            HSSFWorkbook wb = new HSSFWorkbook(file.getInputStream());
            Sheet sheet = wb.getSheetAt(0);
            int rowNum = sheet.getLastRowNum(); //返回行数下标 从0开始
            //前2行都不是内容，所以从2开始
            for (int i = 2; i <= rowNum; i++) {
                Row row = sheet.getRow(i);
                WarehousingRecord warehousingRecord = new WarehousingRecord();
                warehousingRecord.setStatus(WarehousingRecord.STATUS_ENABLE);
                warehousingRecord.setCreateBy(userId);
                warehousingRecord.setCreateDate(Calendar.getInstance().getTime());

                //设置入库时间
                Cell inStockDate = row.getCell(0);
                if (inStockDate!=null){
                    inStockDate.setCellType(CellType.NUMERIC);
//                    inStockDate.setCellType(CellType.);
                    warehousingRecord.setInStockDate(inStockDate.getDateCellValue());
                }

                //设置生产车间
                Cell workshopCell = row.getCell(1);
                if (CellUtil.isCellEmpty(workshopCell)){
                    throw new MessageException("生产车间不能为空");
                }
                warehousingRecord.setWorkshop(workshopCell.getStringCellValue());

                //设置产品id
                Cell productCell = row.getCell(2);
                if (CellUtil.isCellEmpty(productCell)){
                    throw new MessageException("产品名称不能为空");
                }
                List<Product> productFilterResult = productList.stream()
                        .filter(item -> item.getProductName().equals(productCell.getStringCellValue()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(productFilterResult)){
                    throw new MessageException(productCell.getStringCellValue()+"未找到");
                }else{
                    warehousingRecord.setProductId(productFilterResult.get(0).getProductId());
                }

                //设置数量
                Cell numberCell = row.getCell(3);
                Integer number = 0;
                if (!CellUtil.isCellEmpty(numberCell)){
                    number = Integer.parseInt(numberCell.getStringCellValue());
                }
                warehousingRecord.setNumber(number);

                //设置仓库
                Cell stockName = row.getCell(4);
                if (stockName != null ){
                    stockName.setCellType(CellType.STRING);
                    warehousingRecord.setStockName(stockName.getStringCellValue());
                }


                //设置批次
                Cell batchCell = row.getCell(5);
                if (CellUtil.isCellEmpty(batchCell)){
                    throw new MessageException("批次不能为空");
                }
                warehousingRecord.setBatch(batchCell.getStringCellValue());

                //设置生产日期
                Cell produceDate = row.getCell(6);
                if (produceDate != null ){
                    warehousingRecord.setProduceDate(produceDate.getDateCellValue());
                }

                save(warehousingRecord);
            }
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public List<WarehousingRecordVo> getWarehousingRecordByBatchAndProductName(String batch, String productName) {
        List<WarehousingRecordVo> result = warehousingRecordDao.selectRecordList(batch,productName);
        return result;
    }

    @Override
    public WarehousingRecordVo getWarehousingRecordById(Integer warehousingRecordId) {
        WarehousingRecordVo warehousingRecordVo = warehousingRecordDao.selectRecordById(warehousingRecordId);
        return warehousingRecordVo;
    }

    @Override
    public void updateStockById(long productId,Integer lastNum,Integer number) {
        Stock stock;
        List<Stock> stocks = stockDao.selectList(new EntityWrapper<Stock>() {{
            eq("product_id", productId);
        }});

        if (stocks == null || stocks.isEmpty()) {
            stock = new Stock();
            stock.setProductId(productId);
            stock.setNumber(number);
            if (stockDao.insert(stock) != 1)
                throw new MessageException("库存添加失败");
        } else {
            stock = stocks.get(0);
            stock.setProductId(productId);
            stock.setNumber(stock.getNumber()-lastNum+ number);
            if (stockDao.updateById(stock) != 1)
                throw new MessageException("库存修改失败");
        }
    }

    @Override
    public void insertImg(HttpServletRequest request, WarehousingRecord warehousingRecord) {
           MultipartHttpServletRequest muRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = muRequest.getFileMap();
        Iterator<Map.Entry<String, MultipartFile>> iterator = fileMap.entrySet().iterator();
        String url = "";
        while(iterator.hasNext()){
            MultipartFile mFile = iterator.next().getValue();
            try {
                url = sysFileService.upload(mFile.getBytes(), mFile.getOriginalFilename());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        WarehousingRecord warehousingRecord1 = selectById(warehousingRecord);
        String reportImg = warehousingRecord1.getImgUrl();
        if (reportImg != null&& !reportImg.equals("")){
            reportImg=reportImg+','+url;
        }else{
            reportImg = url;
        }
//        System.out.println("id============"+warehousingRecord.getWarehousingRecordId());
//        System.out.println("imgUrl==========="+reportImg);
        warehousingRecord1.setImgUrl(reportImg);
        updateById(warehousingRecord1);
    }

    @Override
    public boolean updateWareById(WarehousingRecord warehousingRecord) {
        if (warehousingRecordDao.updateWareById(warehousingRecord)==1)
            return true;
        return false;
    }
}
